﻿#if NETFX_CORE || WINDOWS_PHONE

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Networking.Sockets;
using Windows.Networking;
using Windows.Storage.Streams;
using System.Runtime.InteropServices.WindowsRuntime;

namespace XmlSockets.Internal.AbSystem
{
    internal class InternalSocket:IInternalSocket
    {
        private StreamSocket socket;

        private InternalSocket():this(new StreamSocket()){}

        private InternalSocket(StreamSocket streamSocket)
        {
            socket = streamSocket;
        }

        public async Task ConnectAsync(string hostName, int port)
        {
            var targetHostName = new HostName(hostName);

            await socket.ConnectAsync(targetHostName, port.ToString());
        }

        public async Task<IXmlSocketReceiveContent> ReceiveAsync(int size)
        {
            var buffer = new Windows.Storage.Streams.Buffer((uint)size);

            //Partialを指定しないと、size分受信するまで完了しない???
            var receive = await socket.InputStream.ReadAsync(buffer,buffer.Capacity,InputStreamOptions.Partial).AsTask().ConfigureAwait(false);
            return new XmlSocketReceiveContent(receive.Length > 0 ? receive.ToArray() : new byte[0], (int)receive.Length);
        }

        public async Task SendAsync(IXmlSocketSendContent content)
        {
            await socket.OutputStream.WriteAsync(content.Buffer.AsBuffer()).AsTask().ConfigureAwait(false);
            await socket.OutputStream.FlushAsync().AsTask().ConfigureAwait(false);
        }

        public void Dispose()
        {
            socket.Dispose();
        }

        public static IInternalSocket Create()
        {
            return new InternalSocket();
        }

        public static IInternalSocket Create(StreamSocket streamSocket)
        {
            return new InternalSocket(streamSocket);
        }

        public IEndPoint LocalEndPoint
        {
            get { return new AbEndPoint(this.socket.Information.LocalAddress, this.socket.Information.LocalPort); }
        }

        public IEndPoint RemorteEndPoint
        {
            get { return new AbEndPoint(this.socket.Information.RemoteAddress, this.socket.Information.RemotePort); }
        }
    }
}
#endif